home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / ToolManager / Source / Library / toolmanager.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  13KB  |  499 lines

  1. /*
  2.  * toolmanager.c  V3.1
  3.  *
  4.  * Library routines
  5.  *
  6.  * Copyright (C) 1990-98 Stefan Becker
  7.  *
  8.  * This source code is for educational purposes only. You may study it
  9.  * and copy ideas or algorithms from it for your own projects. It is
  10.  * not allowed to use any of the source codes (in full or in parts)
  11.  * in other programs. Especially it is not allowed to create variants
  12.  * of ToolManager or ToolManager-like programs from this source code.
  13.  *
  14.  */
  15.  
  16. #include "toolmanager.h"
  17.  
  18. /*
  19.  * Object file dummy entry point
  20.  */
  21. static ULONG Dummy(void)
  22. {
  23.  return(0);
  24. }
  25.  
  26. /* library name and ID string */
  27. #define INTTOSTR(a) #a
  28. static const char LibraryName[] = TMLIBNAME;
  29. static const char LibraryID[]   = "$VER: " TMLIBNAME " " INTTOSTR(TMLIBVERSION)
  30.                                   "." INTTOSTR(TMLIBREVISION) " ("
  31.                                   __COMMODORE_DATE__ ")";
  32.  
  33. /* Constant strings */
  34. const char DosName[] = "dos.library";
  35.  
  36. /* Standard library function prototypes */
  37. __geta4 static struct Library *LibraryInit(__A0 BPTR, __A6 struct Library *);
  38. __geta4 static struct Library *LibraryOpen(__A6 struct ToolManagerBase *);
  39. __geta4 static BPTR            LibraryClose(__A6 struct ToolManagerBase *);
  40. __geta4 static BPTR            LibraryExpunge(__A6 struct ToolManagerBase *);
  41.         static ULONG           LibraryReserved(void);
  42.  
  43. /* Library specific function prototypes */
  44. __geta4 static void            QuitToolManager(void);
  45. __geta4 struct TMHandle       *AllocTMHandle(__A6 struct ToolManagerBase *);
  46. __geta4 static void            FreeTMHandle(__A0 struct TMHandle *);
  47. __geta4 static BOOL            CreateTMObjectTagList(__A0 struct TMHandle *,
  48.                                                      __A1 char *, __D0 ULONG,
  49.                                                      __A2 struct TagItem *);
  50. __geta4 static BOOL            DeleteTMObject(__A0 struct TMHandle *,
  51.                                               __A1 char *);
  52. __geta4 static BOOL            ChangeTMObjectTagList(__A0 struct TMHandle *,
  53.                                                      __A1 char *,
  54.                                                      __A2 struct TagItem *);
  55.  
  56. /* ROMTag structure */
  57. static const struct Resident ROMTag = { RTC_MATCHWORD, &ROMTag, &ROMTag + 1, 0,
  58.  TMLIBVERSION, NT_LIBRARY, 0, LibraryName, LibraryID, LibraryInit
  59. };
  60.  
  61. /* Library functions table */
  62. static const APTR LibraryVectors[] = {
  63.  /* Standard functions */
  64.  (APTR) LibraryOpen,
  65.  (APTR) LibraryClose,
  66.  (APTR) LibraryExpunge,
  67.  (APTR) LibraryReserved,
  68.  
  69.  /* Library specific functions */
  70.  (APTR) LibraryReserved, /* reserved for ARexx */
  71.  (APTR) QuitToolManager,
  72.  (APTR) AllocTMHandle,
  73.  (APTR) FreeTMHandle,
  74.  (APTR) CreateTMObjectTagList,
  75.  (APTR) DeleteTMObject,
  76.  (APTR) ChangeTMObjectTagList,
  77.  
  78.  /* End of table */
  79.  (APTR) -1
  80. };
  81.  
  82. /* Handler process creation data */
  83. static const struct TagItem TMHandlerTags[] = {
  84.  NP_Entry,       (ULONG) ToolManagerHandler,
  85.  NP_CurrentDir,  NULL,
  86.  NP_Name,        (ULONG) TMHANDLERNAME,
  87.  NP_Priority,    0,
  88.  NP_ConsoleTask, NULL,
  89.  NP_WindowPtr,   NULL,
  90.  NP_HomeDir,     NULL,
  91.  TAG_DONE
  92. };
  93.  
  94. /* Library bases */
  95. struct Library         *SysBase;
  96. struct ToolManagerBase *ToolManagerBase;
  97.  
  98. /* Initialize library */
  99. #define DEBUGFUNCTION LibraryInit
  100. __geta4 static struct Library *LibraryInit(__A0 BPTR Segment,
  101.                                            __A6 struct Library *ExecBase)
  102. {
  103.  struct ToolManagerBase *tmb;
  104.  
  105.  /* Initialize SysBase */
  106.  SysBase = ExecBase;
  107.  
  108.  if (tmb = (struct ToolManagerBase *) MakeLibrary(LibraryVectors, NULL, NULL,
  109.                                                 sizeof(struct ToolManagerBase),
  110.                                                 NULL)) {
  111.  
  112.   /* Initialize libray structure */
  113.   tmb->tmb_Library.lib_Node.ln_Type = NT_LIBRARY;
  114.   tmb->tmb_Library.lib_Node.ln_Name = LibraryName;
  115.   tmb->tmb_Library.lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  116.   tmb->tmb_Library.lib_Version      = TMLIBVERSION;
  117.   tmb->tmb_Library.lib_Revision     = TMLIBREVISION;
  118.   tmb->tmb_Library.lib_IdString     = (APTR) LibraryID;
  119.   tmb->tmb_State                    = TMHANDLER_INACTIVE;
  120.   tmb->tmb_Segment                  = Segment;
  121.   tmb->tmb_Port                     = NULL;
  122.  
  123.   /* Add the library to the system */
  124.   AddLibrary((struct Library *) tmb);
  125.  
  126.   /* Set global Library base pointer */
  127.   ToolManagerBase = tmb;
  128.  
  129.   INFORMATION_LOG(KPutStr("\n+++\n\n"))
  130.   INFORMATION_LOG(LOG2(Result, "Base %08lx Segment %08lx\n", tmb, Segment))
  131.  }
  132.  
  133.  return((struct Library *) tmb);
  134. }
  135.  
  136. /* Standard library function: Open */
  137. #undef  DEBUGFUNCTION
  138. #define DEBUGFUNCTION LibraryOpen
  139. __geta4 static struct Library *LibraryOpen(__A6 struct ToolManagerBase *tmb)
  140. {
  141.  struct Library *rc = NULL;
  142.  
  143.  INITDEBUG(ToolManagerLibDebug)
  144.  
  145.  /* Is handler not just closing down? */
  146.  if (tmb->tmb_State != TMHANDLER_LEAVING) {
  147.  
  148.   /* Is handler inactive? */
  149.   if (tmb->tmb_State == TMHANDLER_INACTIVE) {
  150.    struct Library *DOSBase;
  151.  
  152.    /* Yes, start it. First open DOS library */
  153.    if (DOSBase = OpenLibrary(DosName, 39)) {
  154.  
  155.     /* Handler is starting now */
  156.     tmb->tmb_State = TMHANDLER_STARTING;
  157.  
  158.     if ((tmb->tmb_Process = CreateNewProc(TMHandlerTags)) == NULL) {
  159.  
  160.      HANDLER_LOG(LOG0(Handler startup failed))
  161.  
  162.      /* Handler startup failed. Return to inactive state */
  163.      tmb->tmb_State = TMHANDLER_INACTIVE;
  164.     }
  165.  
  166. #ifdef DEBUG
  167.     else {
  168.      INFORMATION_LOG(KPutStr("\n---\n\n"))
  169.      HANDLER_LOG(LOG0(Handler started))
  170.     }
  171. #endif
  172.  
  173.     /* Close DOS library */
  174.     CloseLibrary(DOSBase);
  175.    }
  176.   }
  177.  
  178.   /* Is handler active? */
  179.   if (tmb->tmb_State != TMHANDLER_INACTIVE) {
  180.  
  181.    /* Oh another user :-) */
  182.    tmb->tmb_Library.lib_OpenCnt++;
  183.  
  184.    /* Reset delayed expunge flag */
  185.    tmb->tmb_Library.lib_Flags &= ~LIBF_DELEXP;
  186.  
  187.    /* All OK! */
  188.    rc = (struct Library *) tmb;
  189.  
  190.    INTERFACE_LOG(LOG1(Count, "%ld", tmb->tmb_Library.lib_OpenCnt))
  191.   }
  192.  }
  193.  
  194.  return(rc);
  195. }
  196.  
  197. /* Standard library function: Close */
  198. #undef  DEBUGFUNCTION
  199. #define DEBUGFUNCTION LibraryClose
  200. __geta4 static BPTR LibraryClose(__A6 struct ToolManagerBase *tmb)
  201. {
  202.  BPTR rc = NULL;
  203.  
  204.  /* Open count greater zero and only one user? */
  205.  if ((tmb->tmb_Library.lib_OpenCnt > 0) &&
  206.      (--tmb->tmb_Library.lib_OpenCnt == 0)) {
  207.  
  208.   INTERFACE_LOG(LOG1(Count, "%ld", tmb->tmb_Library.lib_OpenCnt))
  209.  
  210.   /* Last user closed the library. Was handler ordered to shut down? */
  211.   if (tmb->tmb_State == TMHANDLER_CLOSING) {
  212.  
  213.    HANDLER_LOG(LOG0(Handler leaving))
  214.  
  215.    /* Yes, change state */
  216.    tmb->tmb_State = TMHANDLER_LEAVING;
  217.  
  218.    /* Send handler a signal to shut him down */
  219.    Signal(&tmb->tmb_Process->pr_Task, SIGBREAKF_CTRL_F);
  220.   }
  221.  
  222.   /* Is the delayed expunge bit set?  Yes, try to remove the library */
  223.   if (tmb->tmb_Library.lib_Flags & LIBF_DELEXP) rc = LibraryExpunge(tmb);
  224.  }
  225.  
  226.  return(rc);
  227. }
  228.  
  229. /* Standard library function: Expunge */
  230. #undef  DEBUGFUNCTION
  231. #define DEBUGFUNCTION LibraryExpunge
  232. __geta4 static BPTR LibraryExpunge(__A6 struct ToolManagerBase *tmb)
  233. {
  234.  BPTR rc;
  235.  
  236.  INTERFACE_LOG(LOG2(Arguments, "Library %08lx Segment %08lx",
  237.                     tmb, tmb->tmb_Segment))
  238.  
  239.  /* Does anyone use library now or is handler active? */
  240.  if ((tmb->tmb_Library.lib_OpenCnt > 0) ||
  241.      (tmb->tmb_State != TMHANDLER_INACTIVE)) {
  242.  
  243.   /* Yes, library still in use -> set delayed expunge flag */
  244.   tmb->tmb_Library.lib_Flags |= LIBF_DELEXP;
  245.  
  246.   /* Don't expunge library */
  247.   rc = NULL;
  248.  
  249.  } else {
  250.   /* No, remove library */
  251.   Remove(&tmb->tmb_Library.lib_Node);
  252.  
  253.   /* Return BPTR to Library segment */
  254.   rc = tmb->tmb_Segment;
  255.  
  256.   /* Free memory for library base */
  257.   FreeMem((void *) ((ULONG) tmb - tmb->tmb_Library.lib_NegSize),
  258.           tmb->tmb_Library.lib_NegSize + tmb->tmb_Library.lib_PosSize);
  259.  
  260.   INFORMATION_LOG(LOG0(Removing library))
  261.  }
  262.  
  263.  return(rc);
  264. }
  265.  
  266. /* Reserved function, returns NULL */
  267. static ULONG LibraryReserved(void)
  268. {
  269.  return(NULL);
  270. }
  271.  
  272. /* Set quit flag for handler process */
  273. #undef  DEBUGFUNCTION
  274. #define DEBUGFUNCTION QuitToolManager
  275. __geta4 static void QuitToolManager(void)
  276. {
  277.  /* Is handler active? */
  278.  if (ToolManagerBase->tmb_State == TMHANDLER_RUNNING) {
  279.  
  280.   HANDLER_LOG(LOG0(Handler closing))
  281.  
  282.   /* Yes, order him to shut down ASAP */
  283.   ToolManagerBase->tmb_State = TMHANDLER_CLOSING;
  284.  }
  285. }
  286.  
  287. /* Send IPC message */
  288. #undef  DEBUGFUNCTION
  289. #define DEBUGFUNCTION SendIPC
  290. static BOOL SendIPC(struct TMHandle *tmh)
  291. {
  292.  BOOL rc = FALSE;
  293.  
  294.  INTERFACE_LOG(LOG0(Sending command))
  295.  
  296.  /* Handler ready? */
  297.  if (ToolManagerBase->tmb_Port) {
  298.  
  299.   INTERFACE_LOG(LOG0(Handler ready))
  300.  
  301.   /* Yep, send message */
  302.   PutMsg(ToolManagerBase->tmb_Port, (struct Message *) tmh);
  303.  
  304.   /* Wait on reply */
  305.   WaitPort(tmh->tmh_Message.tmm_Msg.mn_ReplyPort);
  306.  
  307.   /* Get reply */
  308.   GetMsg(tmh->tmh_Message.tmm_Msg.mn_ReplyPort);
  309.  
  310.   /* Get return code */
  311.   rc = tmh->tmh_Message.tmm_Command;
  312.  }
  313.  
  314.  return(rc);
  315. }
  316.  
  317. /* Allocate a TMHandle */
  318. #undef  DEBUGFUNCTION
  319. #define DEBUGFUNCTION AllocTMHandle
  320. __geta4 void *AllocTMHandle(__A6 struct ToolManagerBase *tmb)
  321. {
  322.  struct TMHandle *tmh;
  323.  
  324.  INTERFACE_LOG(LOG0(Entry))
  325.  
  326.  /* Allocate memory for handle structure */
  327.  if (tmh = AllocMem(sizeof(struct TMHandle), MEMF_PUBLIC)) {
  328.   struct MsgPort *rp;
  329.   BOOL rc            = FALSE;
  330.  
  331.   INTERFACE_LOG(LOG1(Handle, "0x%08lx", tmh))
  332.  
  333.   /* Create IPC Port */
  334.   if (rp = CreateMsgPort()) {
  335.  
  336.    INTERFACE_LOG(LOG1(Port, "0x%08lx", rp))
  337.  
  338.    /* Initialize message */
  339.    tmh->tmh_Message.tmm_Msg.mn_ReplyPort = rp;
  340.    tmh->tmh_Message.tmm_Msg.mn_Length    = sizeof(struct TMHandle);
  341.    tmh->tmh_Message.tmm_Command          = TMIPC_AllocTMHandle;
  342.  
  343.    /* Check that the handler is already awake */
  344.    if (tmb->tmb_State != TMHANDLER_RUNNING) {
  345.     ULONG delay = 25;
  346.  
  347.     INTERFACE_LOG(LOG0(Waiting for handler to start))
  348.  
  349.     /* Wait up to 5 second for handler to be ready */
  350.     while (delay-- && (tmb->tmb_State != TMHANDLER_RUNNING)) Delay(10);
  351.    }
  352.  
  353.    /* Send command to handler */
  354.    if ((tmb->tmb_State == TMHANDLER_RUNNING) && ((rc = SendIPC(tmh)) == FALSE))
  355.  
  356.     /* Something went wrong, free message port */
  357.     DeleteMsgPort(rp);
  358.   }
  359.  
  360.   /* Error? */
  361.   if (rc == FALSE) {
  362.    FreeMem(tmh, sizeof(struct TMHandle));
  363.    tmh = NULL;
  364.   }
  365.  }
  366.  
  367.  INTERFACE_LOG(LOG1(Result, "Handle 0x%08lx", tmh))
  368.  
  369.  return(tmh);
  370. }
  371.  
  372. /* Free a TMHandle */
  373. #undef  DEBUGFUNCTION
  374. #define DEBUGFUNCTION FreeTMHandle
  375. __geta4 static void FreeTMHandle(__A0 struct TMHandle *tmh)
  376. {
  377.  INTERFACE_LOG(LOG1(Arguments, "Handle 0x%08lx", tmh))
  378.  
  379.  /* Sanity check */
  380.  if (tmh) {
  381.  
  382.   /* Send command to handler */
  383.   tmh->tmh_Message.tmm_Command = TMIPC_FreeTMHandle;
  384.   SendIPC(tmh);
  385.  
  386.   /* Free handle */
  387.   DeleteMsgPort(tmh->tmh_Message.tmm_Msg.mn_ReplyPort);
  388.   FreeMem(tmh, sizeof(struct TMHandle));
  389.  }
  390. }
  391.  
  392. /* Create a TMObject (shared library version) */
  393. #undef  DEBUGFUNCTION
  394. #define DEBUGFUNCTION CreateTMObjectTagList
  395. __geta4 BOOL CreateTMObjectTagList(__A0 struct TMHandle *tmh,
  396.                                    __A1 char *object,
  397.                                    __D0 ULONG type,
  398.                                    __A2 struct TagItem *tags)
  399. {
  400.  BOOL rc = FALSE;
  401.  
  402.  INTERFACE_LOG((LOG5(Arguments,
  403.                  "Handle 0x%08lx Object '%s' (0x%08lx) Type %ld Tags 0x%08lx",
  404.                  tmh, object, object, type, tags),
  405.                 PrintTagList(tags)))
  406.  
  407.  /* Sanity checks */
  408.  if (tmh && object && (type < TMOBJTYPES)) {
  409.  
  410.   /* Build IPC command */
  411.   tmh->tmh_Message.tmm_Command = TMIPC_CreateTMObject;
  412.   tmh->tmh_Message.tmm_Type    = type;
  413.   tmh->tmh_Message.tmm_Object  = object;
  414.   tmh->tmh_Message.tmm_Tags    = tags;
  415.  
  416.   /* Send command to handler */
  417.   rc = SendIPC(tmh);
  418.  }
  419.  
  420.  INTERFACE_LOG(LOG1(Result, "%ld", rc))
  421.  
  422.  return(rc);
  423. }
  424.  
  425. /* Delete a TMObject (shared library version) */
  426. #undef  DEBUGFUNCTION
  427. #define DEBUGFUNCTION DeleteTMObject
  428. __geta4 BOOL DeleteTMObject(__A0 struct TMHandle *tmh, __A1 char *object)
  429. {
  430.  BOOL rc = FALSE;
  431.  
  432.  INTERFACE_LOG(LOG3(Arguments, "Handle 0x%08lx Object '%s' (0x%08lx) ",
  433.                     tmh, object, object))
  434.  
  435.  /* Sanity checks */
  436.  if (tmh && object) {
  437.  
  438.   /* Build IPC command */
  439.   tmh->tmh_Message.tmm_Command = TMIPC_DeleteTMObject;
  440.   tmh->tmh_Message.tmm_Object  = object;
  441.  
  442.   /* Send command to handler */
  443.   rc = SendIPC(tmh);
  444.  }
  445.  
  446.  INTERFACE_LOG(LOG1(Result, "%ld", rc))
  447.  
  448.  return(rc);
  449. }
  450.  
  451. /* Change a TMObject (shared library version) */
  452. #undef  DEBUGFUNCTION
  453. #define DEBUGFUNCTION ChangeTMObjectTagList
  454. __geta4 BOOL ChangeTMObjectTagList(__A0 struct TMHandle *tmh,
  455.                                    __A1 char *object,
  456.                                    __A2 struct TagItem *tags)
  457. {
  458.  BOOL rc = FALSE;
  459.  
  460.  INTERFACE_LOG((LOG4(Arguments,
  461.                      "Handle 0x%08lx Object '%s' (0x%08lx) Tags 0x%08lx",
  462.                      tmh, object, object, tags),
  463.                 PrintTagList(tags)))
  464.  
  465.  /* Sanity checks */
  466.  if (tmh && object) {
  467.  
  468.   /* Build IPC command */
  469.   tmh->tmh_Message.tmm_Command = TMIPC_ChangeTMObject;
  470.   tmh->tmh_Message.tmm_Object  = object;
  471.   tmh->tmh_Message.tmm_Tags    = tags;
  472.  
  473.   /* Send command to handler */
  474.   rc = SendIPC(tmh);
  475.  }
  476.  
  477.  INTERFACE_LOG(LOG1(Result, "%ld", rc))
  478.  
  479.  return(rc);
  480. }
  481.  
  482. /* Try to kill ToolManager */
  483. void QuitTM(void);
  484. #pragma libcall DummyBase QuitTM 24 00
  485. void KillToolManager(void)
  486. {
  487.  struct Library *DummyBase;
  488.  
  489.  /* Open library */
  490.  if (DummyBase = OpenLibrary(LibraryName, 0)) {
  491.  
  492.   /* Tell ToolManager to quit */
  493.   QuitTM();
  494.  
  495.   /* Close library */
  496.   CloseLibrary(DummyBase);
  497.  }
  498. }
  499.